﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using UBCon.Core.Utilities;
using UBCon.Ribbon.SkinManagers;

namespace UBCon.Ribbon
{
    public class RibbonHelper
    {
        /// <summary>
        /// Gets a boolean value which indicates whether specified command source can execute.
        /// (http://referencesource.microsoft.com/#PresentationFramework/src/Framework/MS/Internal/Commands/CommandHelpers.cs)
        /// </summary>
        /// <param name="commandSource"></param>
        /// <returns>true if can execute false otherwise</returns>
        internal static bool CanExecuteCommandSource(ICommandSource commandSource)
        {
            ICommand command = commandSource.Command;
            if (command != null)
            {
                object parameter = commandSource.CommandParameter;
                IInputElement target = commandSource.CommandTarget;

                RoutedCommand routed = command as RoutedCommand;
                if (routed != null)
                {
                    if (target == null)
                    {
                        target = commandSource as IInputElement;
                    }
                    return routed.CanExecute(parameter, target);
                }
                else
                {
                    return command.CanExecute(parameter);
                }
            }

            return false;
        }
 
        /// <summary>
        /// Returns reference to the UBCon.Ribbon.RibbonWindow object that hosts the content tree
        /// within which the dependency object is located.
        /// </summary>
        internal static RibbonWindow GetWindow(DependencyObject sender) 
        {
            Window window = Window.GetWindow(sender);
            if (window is RibbonWindow)
            {
                return window as RibbonWindow;
            }
            return null;
        }

        /// <summary>
        /// Converts a point from a client coordinate space of window into the coordinate space of the screen.
        /// </summary>
        internal static Point TransformToScreen(Point point, Visual relativeTo)
        {
            HwndSource hwndSource = PresentationSource.FromVisual(relativeTo) as HwndSource;
            Visual root = hwndSource.RootVisual;

            // Translate the point from the visual to the root.
            GeneralTransform transformToRoot = relativeTo.TransformToAncestor(root);
            Point pointRoot = transformToRoot.Transform(point);

            // Transform the point from the root to client coordinates.
            Matrix m = Matrix.Identity;
            Transform transform = VisualTreeHelper.GetTransform(root);
            if (transform != null)
            {
                m = Matrix.Multiply(m, transform.Value);
            }

            Vector offset = VisualTreeHelper.GetOffset(root);
            m.Translate(offset.X, offset.Y);
            Point pointClient = m.Transform(pointRoot);

            // Convert from “device-independent pixels” into pixels.
            pointClient = hwndSource.CompositionTarget.TransformToDevice.Transform(pointClient);
            UBCon.Core.NativeMethods.POINT pointClientPixels = new Core.NativeMethods.POINT();
            pointClientPixels.x = (0 < pointClient.X) ? (int)(pointClient.X + 0.5) : (int)(pointClient.X - 0.5);
            pointClientPixels.y = (0 < pointClient.Y) ? (int)(pointClient.Y + 0.5) : (int)(pointClient.Y - 0.5);

            // Transform the point into screen coordinates.
            UBCon.Core.NativeMethods.POINT pointScreenPixels = pointClientPixels;
            UBCon.Core.NativeMethods.ClientToScreen(hwndSource.Handle, pointScreenPixels);

            return new Point(pointScreenPixels.x, pointScreenPixels.y);
        }

        /// <summary>
        /// Gets resource with specified key.
        /// </summary>
        internal static T GetResourceByKey<T>(object key) where T : class 
        {
            try
            {
                if (SkinManager.OfficeBlueTheme != null)
                {
                    return SkinManager.OfficeBlueTheme[key] as T;
                }
                else 
                {
                    return null;
                }
            }
            catch 
            {
                return null;
            }
        }

        /// <summary>
        /// Gets the value of the UBCon.Ribbon.RibbonHelper.ImageHeight attached property for the 
        /// given dependency object.
        /// </summary>
        public static double GetImageHeight(DependencyObject obj)
        {
            return (double)obj.GetValue(ImageHeightProperty);
        }

        /// <summary>
        /// Gets the value of the UBCon.Ribbon.RibbonHelper.ImageHeight attached property for the 
        /// given dependency object.
        /// </summary>
        public static void SetImageHeight(DependencyObject obj, double value)
        {
            obj.SetValue(ImageHeightProperty, value);
        }

        /// <summary>
        /// Identifies UBCon.Ribbon.RibbonHelper.ImageHeight attached property.
        /// </summary>
        public static readonly DependencyProperty ImageHeightProperty =
            DependencyProperty.RegisterAttached("ImageHeight", typeof(double), typeof(RibbonHelper), new PropertyMetadata(7.0D));

        /// <summary>
        /// Gets the value of the UBCon.Ribbon.RibbonHelper.ImageWidth attached property for the 
        /// given dependency object.
        /// </summary>
        public static double GetImageWidth(DependencyObject obj)
        {
            return (double)obj.GetValue(ImageWidthProperty);
        }

        /// <summary>
        /// Sets the value of the UBCon.Ribbon.RibbonHelper.ImageWidth attached property for the 
        /// given dependency object.
        /// </summary>
        public static void SetImageWidth(DependencyObject obj, double value)
        {
            obj.SetValue(ImageWidthProperty, value);
        }

        /// <summary>
        /// Identifies UBCon.Ribbon.RibbonHelper.ImageWidth attached property.
        /// </summary>
        public static readonly DependencyProperty ImageWidthProperty =
            DependencyProperty.RegisterAttached("ImageWidth", typeof(double), typeof(RibbonHelper), new PropertyMetadata(7.0D));


        private static CornerRadius cornerRadius = new CornerRadius(3.0D);

        /// <summary>
        /// Gets the value of the UBCon.Ribbon.RibbonHelper.CornerRadius attached property for the 
        /// given dependency object.
        /// </summary>
        internal static CornerRadius GetCornerRadius(DependencyObject obj)
        {
            return (CornerRadius)obj.GetValue(CornerRadiusProperty);
        }

        /// <summary>
        /// Sets the value of the UBCon.Ribbon.RibbonHelper.CornerRadius attached property for the 
        /// given dependency object.
        /// </summary>
        internal static void SetCornerRadius(DependencyObject obj, CornerRadius value)
        {
            obj.SetValue(CornerRadiusProperty, value);
        }

        /// <summary>
        /// Identifies UBCon.Ribbon.RibbonHelper.CornerRadius attached property.
        /// </summary>
        internal static readonly DependencyProperty CornerRadiusProperty =
            DependencyProperty.RegisterAttached("CornerRadius", typeof(CornerRadius), typeof(RibbonHelper), new PropertyMetadata(cornerRadius));

        /// <summary>
        /// 
        /// </summary>
        internal static Point emptyPoint = new Point(0,0);

        /// <summary>
        /// 
        /// </summary>
        internal static Rect arrangeRect = new Rect();
        //internal static bool ParentContains
    }
}
